library navigation_bar;

import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'indicator.dart' as indicator;

export 'indicator.dart' show IndicatorAxisAlignment;

class NavigationBar extends StatefulWidget {
  final List<String>? items;
  final TabController? controller;
  final Color? selectColor;
  final Color? normalColor;
  final TextStyle? selectStyle;
  final TextStyle? normalStyle;
  final _Indicator? indicator;
  final bool isScrollable;
  final TabBarIndicatorSize indicatorSize;
  final Function(int index)? onChange;

  NavigationBar(
      {@required this.items,
      this.controller,
      this.selectStyle,
      this.normalStyle,
      this.indicator,
      this.onChange,
      this.isScrollable = false,
      this.selectColor = Colors.black,
      this.normalColor = Colors.black12,
      this.indicatorSize = TabBarIndicatorSize.label}) {
    assert(items != null, '列表项不能为空');
  }

  @override
  State<StatefulWidget> createState() => NavigationBarState();
}

class NavigationBarState extends State<NavigationBar> {
  TabController? _controller;
  int _index = 0;
  Future<ui.Image?> get indicatorImage async {
    if (isImageIndicator) {
      ImageIndicator? indicator = widget.indicator as ImageIndicator;
      var image = await loadImage(indicator.image);
      return image;
    }

    return null;
  }

  Future<Decoration> get indicatorDecoration async {
    if (isImageIndicator) {
      if (indicatorImage != null) {
        ImageIndicator imageIndicator = widget.indicator;
        return indicator.ImageIndicator(
          image: await indicatorImage,
          color: imageIndicator.color,
          width: imageIndicator.width,
          height: imageIndicator.height,
          alignment: imageIndicator.alignment,
          marginBottom: imageIndicator.marginBottom,
        );
      }

      return null;
    } else {
      RoundRectIndicator rectIndicator = widget.indicator as RoundRectIndicator;
      return indicator.RoundRectIndicator(
        color: rectIndicator.color,
        width: rectIndicator.width,
        height: rectIndicator.height!,
        round: rectIndicator.round,
        marginBottom: rectIndicator.marginBottom!,
      );
    }
  }

  bool get isImageIndicator {
    return widget.indicator is ImageIndicator;
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (_controller != _getTabController()) {
      initController();
    }
  }

  @override
  void didUpdateWidget(covariant NavigationBar oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (_controller != _getTabController()) {
      initController();
    }
  }

  void initController() {
    if (widget.onChange != null) {
      _controller = _getTabController();
      if (_controller == null) {
        Future.delayed(Duration.zero).then((value) {
          _controller = DefaultTabController.of(context);
          initEvnet();
        });
      } else {
        initEvnet();
      }
    }
  }

  void initEvnet() {
    _controller?.removeListener(listenerCallback);
    _controller?.addListener(listenerCallback);
  }

  void listenerCallback() {
    if (_index == _controller?.index) {
      return;
    }
    _index = _controller!.index;
    widget.onChange!(_index);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Decoration>(
        future: indicatorDecoration,
        builder: (BuildContext context, snapshot) {
          if (!snapshot.hasData) {
            return SizedBox();
          }
          return TabBar(
            tabs: widget.items!.map((text) {
              return Container(
                  height: double.infinity,
                  alignment: Alignment.center,
                  child: Text(
                    text,
                  ));
            }).toList(),
            controller: widget.controller,
            isScrollable: widget.isScrollable,
            labelStyle:
                TextStyle.lerp(TextStyle(height: 1), widget.selectStyle, 1),
            unselectedLabelStyle:
                TextStyle.lerp(TextStyle(height: 1), widget.normalStyle, 1),
            labelColor: widget.selectColor,
            unselectedLabelColor: widget.normalColor,
            indicatorSize: widget.indicatorSize,
            indicator: snapshot.data,
            indicatorColor: Colors.transparent,
          );
        });
  }

  TabController _getTabController() {
    if (widget.controller != null) {
      return widget.controller!;
    } else {
      return DefaultTabController.of(context)!;
    }
  }

  Future<ui.Image?> loadImage(String? path) async {
    if (path == null) {
      return null;
    }
    var data = await rootBundle.load(path);
    var codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
    var info = await codec.getNextFrame();
    return info.image;
  }
}

class _Indicator {
  final Color? color;
  final double? width;
  final double? height;
  final double? marginBottom;

  _Indicator({this.color, this.height, this.width, this.marginBottom = 0});
}

class ImageIndicator extends _Indicator {
  String image;
  indicator.IndicatorAxisAlignment alignment;

  ImageIndicator(
      {@required this.image,
      Color color,
      double width,
      double height,
      this.alignment = indicator.IndicatorAxisAlignment.center,
      double marginBottom = 0})
      : super(
            color: color,
            width: width,
            height: height,
            marginBottom: marginBottom) {
    assert(image != null, "ImageIndicator image不能为空");
  }
}

class RoundRectIndicator extends _Indicator {
  double round;
  RoundRectIndicator(
      {this.round = 1,
      @required Color? color,
      double? width,
      double? height = 2,
      double? marginBottom})
      : super(
            color: color,
            width: width,
            height: height,
            marginBottom: marginBottom);
}
